package com.zhss.dfs.test;

import sun.management.FileSystemImpl;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Iterator;
import java.util.concurrent.TimeUnit;

/**
 * @program: filesystem
 * @description: 上传文件
 * @author: Liu Weidong
 * @create: 2024-05-15 22:11
 **/
public class NIOClient {


    public static void main(String[] args) throws IOException {
        String path = "C:\\Users\\gckj\\Pictures\\ad.jpg";
        byte[] bytes = Files.readAllBytes(Paths.get(path));
        long size = bytes.length;
        System.out.println("文件大小为：" + size);
        sendFile("stds.jpg", bytes, size,"localhost",7799);
    }

    /**
     * 下载文件
     *
     * @param fileName 文件名
     * @param hostName dataNode域名
     * @param port     dataNode端口
     */
    public static Boolean sendFile(String fileName, byte[] file, Long fileSize, String hostName, Integer port)  {
        SocketChannel socketChannel = null;
        Selector selector = null;
        try {
            selector = Selector.open();
            socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress(hostName, port));
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
            ByteBuffer buffer = null;
            // 是否正在发送标识
            boolean sending = true;
            while (sending) {
                selector.select();
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    iterator.remove();
                    if (selectionKey.isConnectable()) {
                        socketChannel = (SocketChannel) selectionKey.channel();
                        if (socketChannel.isConnectionPending()) {
                            while(!socketChannel.finishConnect()){
                                TimeUnit.MILLISECONDS.sleep(100);
                            }
                            // 封装文件数据请求
                            buffer = ByteBuffer.allocate(fileSize.intValue());
                            buffer.put(file);
                            buffer.flip();
                            int sendData = socketChannel.write(buffer);
                            System.out.println("已经发送了" + sendData + "的数据");
                            if (buffer.hasRemaining()) {
                                System.out.println("本次数据没有发送完毕，下次将继续发送。。。。");
                                selectionKey.interestOps(SelectionKey.OP_WRITE);
                            } else {
                                selectionKey.interestOps(SelectionKey.OP_READ);
                            }
                        }
                        else if (selectionKey.isWritable()) {
                            socketChannel = (SocketChannel)selectionKey.channel();
                            int sendData = socketChannel.write(buffer);
                            System.out.println("上次数据包没有发送完毕，本次继续发送：" + sendData + "bytes");
                            if (!buffer.hasRemaining()) {
                                selectionKey.interestOps(SelectionKey.OP_WRITE);
                            } else {
                                selectionKey.interestOps(SelectionKey.OP_READ);
                            }
                        }
                    } else if (selectionKey.isReadable()) {
                        socketChannel = (SocketChannel) selectionKey.channel();
                        buffer = ByteBuffer.allocate(1024);
                        int read = socketChannel.read(buffer);
                        if (read > 0) {
                            System.out.println("线程:" + Thread.currentThread().getName()
                                    + "接收到响应： " + new String(buffer.array(), 0, read));
                            sending = false;
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (socketChannel != null) {
                try {
                    socketChannel.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
            if (selector != null) {
                try {
                    selector.close();
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        }
        return true;
    }
}
